package org.third.integration.kubernates.cmd.imp;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import org.apache.http.client.methods.HttpGet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.util.UriComponentsBuilder;
import org.third.common.SS_CONSTANT;
import org.third.common.exception.ConvertJsonException;
import org.third.common.utils.EnvUtils;
import org.third.common.utils.HttpRequestUtil;
import org.third.integration.kubernates.cmd.ConfigMapListDTO;
import org.third.integration.kubernates.cmd.KubectlGet;
import org.third.integration.kubernates.cmd.imp.api.K8sApiBuilder;
import org.third.integration.kubernates.cmd.imp.bean.KubeImageInfo;
import org.third.integration.kubernates.cmd.imp.bean.KubeImageInfoList;
import org.third.integration.kubernates.cmd.imp.bean.KubeImageNameList;
import org.third.integration.kubernates.cmd.imp.bean.KubeInstanceInfo;
import org.third.integration.kubernates.cmd.imp.client.KubeRquestClient;
import org.third.integration.kubernates.cmd.imp.client.bean.ApiServerResponse;
import org.third.integration.kubernates.cmd.imp.exp.NotValidK8sYamlException;
import org.third.integration.kubernates.cmd.imp.exp.RequestApiServerException;
import org.third.integration.kubernates.cmd.imp.utils.K8S_TYPE_UTILS;
import org.third.web.bean.ImageSetDTO;
import org.third.web.bean.PortalsToken;

import java.awt.Image;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Component
public class KubectlGetImp implements KubectlGet{
	
	private final Logger logger = LoggerFactory.getLogger(KubectlGetImp.class);

	ObjectMapper objectMapper = new ObjectMapper();
	
	@Autowired
	private K8sApiBuilder k8sApiBuilder;
	
	@Autowired
	KubeRquestClient kubeRquestClient;

	@Autowired
	private HttpRequestUtil httpRequestUtil;
	

	@Override
	public KubeInstanceInfo getStatus(String type, String apiVersion,
			String namespace, String instanceName)
			throws NotValidK8sYamlException, RequestApiServerException {
		// TODO Auto-generated method stub

		KubeInstanceInfo kubeInstanceInfo = validateInput(type, apiVersion, namespace, instanceName);		
		String url = k8sApiBuilder.buildAPI(kubeInstanceInfo.getNamespace(), kubeInstanceInfo.getApiVersion(), kubeInstanceInfo.getType(), kubeInstanceInfo.getInstanceName());
		url=url+"/status";	
//		url="https://SHCLITVM0144.hpeswlab.net:8443/api/v1/namespaces/core/persistentvolumeclaims/itom-vol-claim/status";
		requestK8s(kubeInstanceInfo, url);
//		if(kubeInstanceInfo.getStatusCode()!=200){
//			return false;
//		}
//		String json="{\"kind\":\"PersistentVolumeClaim\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"itom-vol-claim\",\"namespace\":\"core\",\"selfLink\":\"/api/v1/namespaces/core/persistentvolumeclaims/itom-vol-claim/status\",\"uid\":\"9cb6d875-3d0c-11e7-a8bf-005056b338b2\",\"resourceVersion\":\"983302\",\"creationTimestamp\":\"2017-05-20T03:30:03Z\",\"labels\":{\"kubernetes.io/cluster-service\":\"true\"},\"annotations\":{\"pv.kubernetes.io/bind-completed\":\"yes\",\"pv.kubernetes.io/bound-by-controller\":\"yes\"}},\"spec\":{\"accessModes\":[\"ReadWriteMany\"],\"selector\":{\"matchLabels\":{\"kubernetes.io/cluster-service\":\"true\"}},\"resources\":{\"requests\":{\"storage\":\"50Gi\"}},\"volumeName\":\"itom-vol\"},\"status\":{\"phase\":\"Bound\",\"accessModes\":[\"ReadWriteMany\"],\"capacity\":{\"storage\":\"50Gi\"}}}";
		return kubeInstanceInfo;	
	}
	










	@Override
	public KubeInstanceInfo execute(String type, String apiVersion,
			String namespace, String instanceName) throws NotValidK8sYamlException, RequestApiServerException {
		
		KubeInstanceInfo kubeInstanceInfo = validateInput(type, apiVersion, namespace, instanceName);
		
		String url = k8sApiBuilder.buildAPI(kubeInstanceInfo.getNamespace(), kubeInstanceInfo.getApiVersion(), kubeInstanceInfo.getType(), kubeInstanceInfo.getInstanceName());
				
		requestK8s(kubeInstanceInfo, url);
		
		return kubeInstanceInfo;
	}

	@Override
	public KubeImageInfoList getAllImages() throws NotValidK8sYamlException,
			RequestApiServerException {
		KubeImageInfoList kubeImageInfoList = new KubeImageInfoList();
		if (SS_CONSTANT.LOCAL_SUITE_REGISTRY.equals(EnvUtils.getSuiteRegistry())){
			logger.info("run the old method to get all images");
			return getKubeImageInfoListOld();
		}else{
			//modify by bing 2018-04-11
			KubeImageInfo kubeImageInfo = new KubeImageInfo();
			List<String> tags = new ArrayList<>();
			tags.add(EnvUtils.getSuiteRegistry());
			kubeImageInfo.setName("Dont support to query "+EnvUtils.getSuiteRegistry());
			kubeImageInfo.setTags(tags);
			List<KubeImageInfo> kubeImageInfos = new ArrayList<>();
			kubeImageInfos.add(kubeImageInfo);
			kubeImageInfoList.setImages(kubeImageInfos);

			return kubeImageInfoList;
		}
	}

	private KubeImageInfoList getKubeImageInfoListNew()  {
		KubeImageInfoList kubeImageInfoList=new KubeImageInfoList();
		List<KubeImageInfo> kubeImageInfos = new ArrayList<>();

		// get all images and tags from pod : /tmp/offline_sync_tools/image-set.json
		String imageSetJson = "";
		ImageSetDTO imageSet = null;
		String imageNamePrefix = "";
		try {
			imageSetJson = new String(Files.readAllBytes(Paths.get("/tmp/offline_sync_tools/image-set.json")));
			if (!StringUtils.isEmpty(imageSetJson)){
				imageSet = objectMapper.readValue(imageSetJson, ImageSetDTO.class);
			}
			if (imageSet == null){
				throw new ConvertJsonException("cannot convert image-set.json content into ImageSetDTO object");
			}
			imageNamePrefix = System.getenv("REGISTRY_ORGNAME")+"/";
			/*Set<Image> images = imageSet.getImages();
			for (Image image:images){
				String imageName =imageNamePrefix + image.getImage().split(":")[0];
				String imageTag = image.getImage().split(":")[1];
				String url = k8sApiBuilder.buildApiforImageWitgTag(imageName, imageTag);
				logger.info("url==============="+url);
				ResponseEntity responseEntity = null;
				try {
					responseEntity = httpRequestUtil.callHttpsRquest(HttpMethod.GET, url, null, null, String.class,null);
				} catch (HttpClientErrorException e) {
					if (e.getStatusCode()== HttpStatus.UNAUTHORIZED){
						String requestTokenUrl = getRequestTokenUrl(e.getResponseHeaders().get(HttpHeaders.WWW_AUTHENTICATE));
						ResponseEntity<PortalsToken> tokenResponseEntity = null;
						try {
							String token = "";
							tokenResponseEntity = httpRequestUtil.callHttpsRquest(HttpMethod.GET,requestTokenUrl,null,null,PortalsToken.class,null);
							if (tokenResponseEntity.getStatusCode()==HttpStatus.OK){
								token = tokenResponseEntity.getBody().getToken();
							}
							logger.info("request for oprtal token is : " + token);
							if (!StringUtils.isEmpty(token)){
								responseEntity = httpRequestUtil.callHttpsRquest(HttpMethod.GET, url, token, null, String.class,null);
							}
						} catch (HttpClientErrorException requestTokenException) {
							logger.warn("request for "+imageName+":"+imageTag+" failed:"+requestTokenException.getMessage());
							continue;
						}
					}
					if (responseEntity!=null && responseEntity.getStatusCode()==HttpStatus.OK){
						KubeImageInfo kubeImageInfo = new KubeImageInfo();
						List<String> tags = new ArrayList<>();
						kubeImageInfo.setName(imageName);
						tags.add(imageTag);
						kubeImageInfo.setTags(tags);
						kubeImageInfos.add(kubeImageInfo);
					}
				}
			}*/
			kubeImageInfoList.setImages(kubeImageInfos);
		} catch (IOException e) {
			logger.error("can't get image-set.json file:"+ e.getMessage());
			return kubeImageInfoList;
		}

		return kubeImageInfoList;
	}

	private String getRequestTokenUrl(List<String> list) {
		String url = "";
		for (String headerValue:list) {
            if (headerValue.contains("realm")&&headerValue.contains("service")&&headerValue.contains("scope")){
                String[] headerValues = headerValue.split(",");
                StringBuffer sb = new StringBuffer();
				UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(getQueryParamValue(headerValues[0]))
                        .queryParam(getQueryParamName(headerValues[1]), getQueryParamValue(headerValues[1]))
                        .queryParam(getQueryParamName(headerValues[2]), getQueryParamValue(headerValues[2]));
				logger.info("request token url is:"+ builder.toUriString());
				url = builder.toUriString();
			}
		}
		return url;
	}

	private String getQueryParamValue(String headerValue) {
		return headerValue.substring(headerValue.indexOf("\"")+1,headerValue.lastIndexOf("\""));
	}

	private String getQueryParamName(String headerValue) {
		return headerValue.substring(0,headerValue.indexOf("="));
	}

	private KubeImageInfoList getKubeImageInfoListOld() throws RequestApiServerException {
		String url = k8sApiBuilder.buildAPI("all", "_catalog");
		url = url+"?n=5000";
		HttpGet httpGet = new HttpGet(url);
		KubeImageInfoList kubeImageInfoList=new KubeImageInfoList();
		List<KubeImageInfo> initkubeImageInfoList=new ArrayList<KubeImageInfo>();
		kubeImageInfoList.setImages(initkubeImageInfoList);
		KubeImageNameList kubeImageNameList =new KubeImageNameList();
		ApiServerResponse apiServerResponse = kubeRquestClient.requestK8s(httpGet);
		if(apiServerResponse.getException() != null){
             throw new RequestApiServerException("get imgagename list Failed to request API server", apiServerResponse.getException());
         }
		Gson gson = new Gson();
		KubeImageNameList kubeImageNameListObject=gson.fromJson(apiServerResponse.getResponseBody(),KubeImageNameList.class );
		if(kubeImageNameListObject==null){
            logger.info("the imagelist is null so we cannot get imagelist");
            kubeImageInfoList.setImages(new ArrayList());
            return kubeImageInfoList;
        }

		if(kubeImageNameListObject.getRepositories()==null) {
            logger.info("the imagelist is null so we cannot get imagelist to exec getRepositories method");
            kubeImageInfoList.setImages(new ArrayList());
            return kubeImageInfoList;
        }else{
              for(String imageName : kubeImageNameListObject.getRepositories()) {
                  String urltag=k8sApiBuilder.buildAPI("oneType", imageName);
                  HttpGet httpGettag = new HttpGet(urltag);
                  KubeImageInfo  kubeImageInfoTag=new KubeImageInfo();
                  ApiServerResponse apiServerResponseTag = kubeRquestClient.requestK8s(httpGettag);
                  if(apiServerResponseTag.getException() != null){
                      throw new RequestApiServerException("Failed to request API server apiServerResponseTag", apiServerResponseTag.getException());
                  }
                  //二次解析string转换成json字符串
                  Gson gsontag = new Gson();
                  KubeImageInfo kubeInforObject=gsontag.fromJson(apiServerResponseTag.getResponseBody(),KubeImageInfo.class);
                     if(kubeInforObject!=null&&
                          (apiServerResponseTag.getStatusCode()==200 ||apiServerResponseTag.getStatusCode()==201)
                          ){
                         kubeImageInfoList.getImages().add(kubeInforObject);
                     }
               }
              //return the json we want
              return  kubeImageInfoList;
         }
	}

	private KubeInstanceInfo validateInput(String type, String apiVersion,
			String namespace, String instanceName)
			throws NotValidK8sYamlException {
		if(!K8S_TYPE_UTILS.getSpecificTypes().contains(type) && StringUtils.isEmpty(namespace)){
			throw new RuntimeException("namespace can't be empty ");
		}
		if(StringUtils.isEmpty(instanceName) || StringUtils.isEmpty(apiVersion) || StringUtils.isEmpty(type)){
			throw new RuntimeException("type or apiVersion or name can't be empty");
		}
		KubeInstanceInfo kubeInstanceInfo = new KubeInstanceInfo(type, apiVersion, instanceName, namespace, null);
		
		return kubeInstanceInfo;
	}
	
	private void requestK8s(KubeInstanceInfo kubeInstanceInfo, String url) throws RequestApiServerException {
		HttpGet httpGet = new HttpGet(url);		
		ApiServerResponse apiServerResponse = kubeRquestClient.requestK8s(httpGet);
		kubeInstanceInfo.setStatusCode(apiServerResponse.getStatusCode());
		kubeInstanceInfo.setResponseBody(apiServerResponse.getResponseBody());
		if(apiServerResponse.getException() != null){
			throw new RequestApiServerException("Failed to request API server", apiServerResponse.getException());
		}
	}

	@Override
	public KubeInstanceInfo getAll(String type, String apiVersion,
			String namespace, String urlArgs) throws NotValidK8sYamlException,
			RequestApiServerException {
		
		KubeInstanceInfo kubeInstanceInfo = new KubeInstanceInfo(type, apiVersion, null, namespace, null);
		
		String url = k8sApiBuilder.buildAPI(kubeInstanceInfo.getNamespace(), kubeInstanceInfo.getApiVersion(), kubeInstanceInfo.getType());
		
		if(!StringUtils.isEmpty(urlArgs)){
			url = url + "?" + urlArgs;
		}
		
		requestK8s(kubeInstanceInfo, url);
		
		return kubeInstanceInfo;
	}
	
	

	@Override
	public ConfigMapListDTO getAllList(String namespace, String type, String queryType) throws IOException{
		String url = k8sApiBuilder.buildListApi(namespace,type,queryType);
		HttpGet httpGet = new HttpGet(url);
		ApiServerResponse response = kubeRquestClient.requestK8s(httpGet);
		//TODO waiting test
		ConfigMapListDTO configMapListDTO = new ConfigMapListDTO();
		if(response.getStatusCode() == 200) {
			configMapListDTO = objectMapper.readValue(response.getResponseBody(),ConfigMapListDTO.class);
		}
		return configMapListDTO;
	}
}
